<?php

require_once 'SpecHelper.php';
require_once 'PHPMock.php';
require_once '_helpers/Album.php';

class DescribePHPMock extends PHPSpec_Context
{

    /**public function itShouldCreateMockInheritingClassTypeFromOriginal()
    {
        $mock = PHPMock::mock('PHPMockSpec_Album');
        $this->spec($mock)->should->beAnInstanceOf('PHPMockSpec_Album');
    }

    public function itShouldCreateMockInheritingTypeIfOriginalAnInterface()
    {
        $mock = PHPMock::mock('PHPMockSpec_AlbumInterface');
        $this->spec($mock)->should->beAnInstanceOf('PHPMockSpec_AlbumInterface');
    }

    public function itShouldCreateMockInheritingTypeIfOriginalAnInterfaceWithConstructorDefinition()
    {
        $mock = PHPMock::mock('PHPMockSpec_AlbumInterfaceWithCtor');
        $this->spec($mock)->should->beAnInstanceOf('PHPMockSpec_AlbumInterfaceWithCtor');
    }

    public function itShouldCreateMockWithSpecifiedName()
    {
        $mock = PHPMock::mock('PHPMockSpec_AlbumInterface', 'MyAlbumClass');
        $this->spec($mock)->should->beAnInstanceOf('MyAlbumClass');
    }

    public function itShouldCreateStubFromAnArrayOfMethodsAndReturnValues()
    {
        $mock = PHPMock::mock('PHPMockSpec_AlbumInterface', array('getName'=>'SomeName'));
        $this->spec($mock->getName())->should->be('SomeName');
    }

    public function itShouldThrowExceptionIfClassIsFinal()
    {
        try {
            $mock = PHPMock::mock('PHPMockSpec_AlbumFinal');
            $this->fail();
        } catch (PHPMock_Exception $e) {
        }
    }

    public function itShouldThrowExceptionIfClassDoesNotExist()
    {
        try {
            $mock = PHPMock::mock('PHPMockSpec_DoesNotExist');
            $this->fail();
        } catch (PHPMock_Exception $e) {
        }
    }

    public function itShouldNotThrowClassNotExistsExceptionIfAnInterface()
    {
        try {
            $mock = PHPMock::mock('PHPMockSpec_AlbumInterface');
        } catch (PHPMock_Exception $e) {
            $this->fail();
        }
    }

    public function itShouldMockAllAllowedPublicMethodsWhichDoNothingSinceMocked()
    {
        $albumMock = PHPMock::mock('PHPMockSpec_Album');
        $albumMock->shouldReceive('setName')->with('Highway To Hell');
        $albumMock->shouldReceive('getName');
        $albumMock->setName('Highway To Hell');
        $this->spec($albumMock->getName())->should->beNull();
    }

    public function itShouldMockPublicStaticMethodsWhichDoNothingSinceMocked()
    {
        $this->pending('Static methods will need static handling');
        $phpmock = PHPMock::mock('PHPMockSpec_Album');
        $mockClass = $phpmock->getMockClassName();
        call_user_func(array($mockClass, 'setGenre'), 'Rock\'n\'Roll');
        $this->spec(call_user_func(array($mockClass, 'getGenre')))->should->beNull();
    }

    public function itShouldRetainMethodParameterDefinitionsInMocks()
    {
        $mock = PHPMock::mock('PHPMockSpec_Album');
        $mockClass = get_class($mock);
        $class = new ReflectionClass($mockClass);
        $setArtist = $class->getMethod('setArtist');
        $setArtistParams = $setArtist->getParameters();
        $paramString = $this->getParameterDefinition($setArtistParams[0]);
        $this->spec($paramString)->should->be('PHPMockSpec_Artist $artist = NULL');
    }
    
    public function itShouldReturnTrueOnValidationByDefaultIfNoExpectationsSet()
    {
        $mock = PHPMock::mock('PHPMockSpec_Album');
        try {
            $this->spec($mock)->verify()->should->beTrue();
        } catch (Exception $e) {
            $this->fail('Mock object checking threw an Exception reading: ' . $e->getMessage());
        }
    }**/

    public function getParameterDefinition($param)
    {
        $paramDef = '';
        if ($param->isArray()) {
            $paramDef .= 'array ';
        } elseif ($param->getClass()) {
            $paramDef .= $param->getClass()->getName() . ' ';
        }
        $paramDef .= '$' . $param->getName();
        if ($param->isOptional()) {
            $paramDef .= ' = ';
            if ($param->isDefaultValueAvailable()) {
                $paramDef .= var_export($param->getDefaultValue(), true);
            }
        }
        return $paramDef;
    }

}